﻿//
// NativeMethods.cs
//
// Authors:
//    Claus Jørgensen <10229@iha.dk>
//    Jens Bloch Christensen <09584@iha.dk>
//    Jonas Daugaard Møller <08814@iha.dk>
//
using System.Runtime.InteropServices;

namespace RSD.Robot
{
    #region Function Pointers (Delegates)

    /// <summary>
    /// Movement delegate for the robot's movement callbacks.
    /// </summary>
    /// <param name="axis">The axis being moved.</param>
    [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
    internal delegate void MovementCallback(byte axis);

    /// <summary>
    /// WatchControl delegate for the robot's watch-control callback.
    /// </summary>
    /// <param name="axisStatus">Axis status from the current control status.</param>
    [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
    internal delegate void WatchControlCallback(uint axisStatus);

    /// <summary>
    /// HomingNotifier delegate for the robot's homing-notifier callback.
    /// </summary>
    /// <param name="homingStatus">Homing status code.</param>
    [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
    internal delegate void HomingNotifierCallback(char homingStatus);

    /// <summary>
    /// WatchJoint delegate for the robot's watch-joint callback.
    /// </summary>
    /// <param name="robotData">The robots joint data.</param>
    [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
    internal delegate void WatchJointCallback(int[] robotData);

    /// <summary>
    /// IOMonitor delegate for the robot's digital input/output monitoring callbacks.
    /// </summary>
    /// <param name="status">IO status code.</param>
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    internal delegate void IOMonitorCallback(int status);

    /// <summary>
    /// InitializationCompleted delegate for the robot's initialization-completed callback.
    /// </summary>
    /// <param name="configuration">Robot configuration.</param>
    [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
    internal delegate void InitializationCompleteCallback(USBCConfiguration configuration);

    /// <summary>
    /// Error delegate for the robot's error callback.
    /// </summary>
    /// <param name="error">Error information.</param>
    [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
    internal delegate void ErrorCallback(USBCError error);

    #endregion

    /// <summary>
    /// Native methods for USBC.dll
    /// </summary>
    /// <exception cref="T:System.DllNotFoundException">If the USBC.dll is not found.</exception>
    internal static class NativeMethods
    {
        /// <summary>
        /// Path to the USBC.dll library. 
        /// </summary>
        public const string DllName = "USBC.dll";

        #region Configuration

        /// <summary>
        /// Finds the USB device connected to the robot and initializes the connection 
        /// between the robot and the computer.
        /// </summary>
        /// <remarks>
        /// The functions return value does not indicate a succesful initialization, 
        /// only a call to <paramref name="initializationCompleted"/> indicates a succesfull initialization.
        /// Initialization may not call back at all, so it's a good idea to wrap the call to 
        /// this function around a timer (5 seconds should be enough).
        /// <para />
        /// The connection between the robot and the libary is uniquely tied to the process 
        /// calling this function. Simulation-mode allows you to use the library as the robot 
        /// was online and homed. Only one connection to the robot is possible.
        /// </remarks>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        /// <param name="initializationMode">Initialization mode.</param>
        /// <param name="systemType">System type.</param>
        /// <param name="initializationCompleted">InitializationCompleted callback.</param>
        /// <param name="error">Error callback.</param>
        [DllImport(NativeMethods.DllName, EntryPoint = "?Initialization@@YAHFFP6AXPAX@Z1@Z",
            CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool Initialization(short initializationMode, [Optional] short systemType,
            [MarshalAs(UnmanagedType.FunctionPtr)][Optional] InitializationCompleteCallback initializationCompleted,
            [MarshalAs(UnmanagedType.FunctionPtr)][Optional] ErrorCallback error);

        /// <summary>
        /// Set the folder which holds the files with values the motors on the robot.
        /// </summary>
        /// <remarks>
        /// The parameter folders are defined in ERCONF.ini
        /// </remarks>
        /// <param name="folderName">Relative path of the parameter folder.</param>
        /// <returns>true if a new folder has been set; otherwise, false.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?SetParameterFolder@@YAHPAD@Z",
            CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool SetParameterFolder(string folderName);

        /// <summary>
        /// Gets the folder which holds the files with values the motors on the robot.
        /// </summary>
        /// <remarks>
        /// The parameter folders are defined in ERCONF.ini
        /// </remarks>
        /// <param name="folderName">
        /// When this method returns, contains relative path of the parameter folder.
        /// </param>
        /// <returns>true if the string has been filled; otherwise false.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?GetParameterFolder@@YAHPAD@Z",
            CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool GetParameterFolder([Out] string folderName);

        /// <summary>
        /// Closes the connection to the robot.
        /// </summary>
        [DllImport(NativeMethods.DllName, EntryPoint = "?CloseUSBC@@YAXXZ",
            CallingConvention = CallingConvention.Cdecl)]
        internal static extern void CloseUSBC();

        /// <summary>
        /// Gets the robot version number.
        /// </summary>
        /// <param name="version">
        /// When this method returns, contains the robots version.
        /// </param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?GetVersion@@YAHPAK@Z",
            CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool GetVersion([Out] uint version);

        /// <summary>
        /// Indicates whether the emergency button has activated or not.
        /// </summary>
        /// <returns>true if the emergency button has been activated; otherwise false.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?IsEmergency@@YAHXZ",
            CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool IsEmergency();

        /// <summary>
        /// Indicates whether the robot is in teaching mode or not.
        /// </summary>
        /// <returns>true if the robot is in teaching mode; otherwise false.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?IsTeachMode@@YAHXZ",
            CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool IsInTeachingMode();

        /// <summary>
        /// Indicates whether the robot is online.
        /// </summary>
        /// <remarks>In simulation mode, this method always return false.</remarks>
        /// <returns>true if the robot is online; otherwise false.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?IsOnLineOk@@YAHXZ",
            CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool IsOnline();

        /// <summary>
        /// Gets the configuration for the connected robot.
        /// </summary>
        /// <remarks>Requires an initialized robot connection.</remarks>
        /// <param name="config">When this method returns, contains the foldername.</param>
        /// <returns>true if the ConfigData object has been succesfully filled; otherwise false.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?GetConfig@@YAHAAVConfigData@@@Z",
            CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool GetConfiguation([In][Out] USBCConfiguration config);

        #endregion

        #region Input/Output

        /// <summary>
        /// Begins monitoring the digital input.
        /// </summary>
        /// <param name="monitorCallback">Callback used to watch the digital input.</param>
        /// <returns>true if operation was succesful; otherwise false.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?WatchDigitalInp@@YAHP6AXPAX@Z@Z",
            CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool BeginMonitorDigitalInput(IOMonitorCallback monitorCallback);

        /// <summary>
        /// Stops monitoring the digital input.
        /// </summary>
        /// <returns>true if operation was succesful; otherwise false.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?CloseWatchDigitalInp@@YAHXZ",
            CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool EndWatchDigitalInput();

        /// <summary>
        /// Begins monitoring the digital output.
        /// </summary>
        /// <param name="monitorCallback">Callback used to watch the digital output.</param>
        /// <returns>true if operation was succesful; otherwise false.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?WatchDigitalOut@@YAHP6AXPAX@Z@Z",
            CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool BeginMonitorDigitalOutput(IOMonitorCallback monitorCallback);

        /// <summary>
        /// Stops monitoring the digital output.
        /// </summary>
        /// <returns>true if operation was succesful; otherwise false.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?CloseWatchDigitalOut@@YAHXZ",
            CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool EndMonitorDigitalOutput();

        /// <summary>
        /// Gets the digital input.
        /// </summary>
        /// <param name="statusBitmap">Digital input status bitmap.</param>
        /// <returns>true if operation was succesful; otherwise false.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?GetDigitalInputs@@YAHPAK@Z",
            CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool GetDigitalInput([Out] uint statusBitmap);

        /// <summary>
        /// Gets the digital output.
        /// </summary>
        /// <param name="statusBitmap">Digital output status bitmap.</param>
        /// <returns>true if operation was succesful; otherwise false.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?GetDigitalOutputs@@YAHPAK@Z",
            CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool GetDigitalOutput([Out] uint statusBitmap);

        /// <summary>
        /// Sets the digital output.
        /// </summary>
        /// <param name="ioNumber">Output value.</param>
        /// <param name="isOn">Toggles on/off.</param>
        /// <param name="isImmediate">Sets of the operation is immediate or not.</param>
        /// <returns>true if operation was succesful; otherwise false.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?SetDigitalOutput@@YAHFHH@Z",
            CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool SetDigitalOutput(short ioNumber,
            [MarshalAs(UnmanagedType.Bool)] bool isOn,
            [MarshalAs(UnmanagedType.Bool)] bool isImmediate);

        #endregion

        #region Movement

        /// <summary>
        /// Sets the callback functions for movement events.
        /// </summary>
        /// <remarks>
        /// The value of this char denotes on what part of the robot the event has occured: 
        ///     '0'-'7' for axis movements 
        ///     'A'     for robot movements 
        ///     'B'     for peripheral movements 
        ///     'G'     for gripper movements 
        /// <para />
        /// If both parameters are set with non null values, a pointer to the previous fnMotionEnd function will be returned.
        /// </remarks>
        /// <param name="motionEnded">Callback for when the motion have ended.</param>
        /// <param name="motionStarted">Callback for when the motion have started.</param>
        /// <returns>Pointer to the previous callback function.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?WatchMotion@@YAP6AXPAX@ZP6AX0@Z1@Z",
            CallingConvention = CallingConvention.Cdecl)]
        internal static extern MovementCallback WatchMotion(
            [MarshalAs(UnmanagedType.FunctionPtr)] MovementCallback motionEnded,
            [MarshalAs(UnmanagedType.FunctionPtr)] MovementCallback motionStarted);

        /// <summary>
        /// Enter manual movement mode. Must be called in order to use the MoveManual function.
        /// </summary>
        /// <remarks>
        /// The robot must be homed in order to use movement by coordinates.
        /// </remarks>
        /// <param name="manualMode">Movemement move to enable manualmode on.</param>
        /// <returns>Returns true if the robot has succesfully entered manual movement mode, false otherwise.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?EnterManual@@YAHF@Z",
            CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool EnterManual(short manualMode);

        /// <summary>
        /// Manually moves robot.
        /// </summary>
        /// <remarks>
        /// In order to use movement by coordinates, the robot must be homed.
        /// The axis parameters use differs depending on movement mode (set by EnterManual).
        /// <para />
        /// Under movement by axis: 
        ///     0 - Base or Torso 
        ///     1 - Shoulder 
        ///     2 - Elbow 
        ///     3 - Wrist-Pitch 
        ///     4 - Wrist-Roll 
        ///     5 - Gripper 
        ///     7 - Conveyorbelt 
        /// <para />
        /// Under movement by coordinates: 
        ///     0 - X 
        ///     1 - Y 
        ///     2 - Z 
        ///     3 - Pitch 
        ///     4 - Roll 
        /// <para />
        /// MoveManual does not produce any callbacks.
        /// MoveManual need control to be turned on, in order to function properly.
        /// MoveManual automaticly turns on control, if control is off, but cancels all other funtionality during that call.
        /// MoveManual automaticly enters manual movement mode, if the robot is not in manual movement mode, 
        /// but cancels all other funtionality during that call (control takes precedence over manual movement mode).
        /// </remarks>
        /// <param name="axis">Axis to move on.</param>
        /// <param name="velocity">Velocity to move with in percent.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?MoveManual@@YAHEJ@Z",
            CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool MoveManual(byte axis, int velocity);

        /// <summary>
        /// Exits manual movement mode.
        /// </summary>
        /// <returns>true if movemanully has been succesfully exited; otherwise false.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?CloseManual@@YAHXZ",
            CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool CloseManual();

        /// <summary>
        /// Sets the time future movement should take.
        /// </summary>
        /// <remarks>
        /// If the time set is invalid (extremly low or high), the closest possible speed will be automaticly set.
        /// </remarks>
        /// <param name="axis">Movement axis.</param>
        /// <param name="time">Time in miliseconds.</param>
        /// <returns>true if time has been succesfully set; otherwise false.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?Time@@YAHEJ@Z",
            CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool Time(byte axis, int time);

        /// <summary>
        /// Sets the speed future movement should take.
        /// </summary>
        /// <remarks>
        /// If the speed set is invalid (extremly low or high), 
        /// the closest possible speed will be automaticly set (0 is not valid).
        /// </remarks>
        /// <param name="axis">Movement axis.</param>
        /// <param name="speed">Speed in percent.</param>
        /// <returns>true if the speed has been succesfully set; otherwise false.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?Speed@@YAHEJ@Z",
            CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool Speed(byte axis, int speed);

        /// <summary>
        /// Manually sends PWM values directly to a motor.
        /// </summary>
        /// <remarks>
        /// CAUTION: There is no impact protection when using this function, and can potentially burn the motors.
        /// Control must be off while using this function.
        /// </remarks>
        /// <param name="axis">Movement axis.</param>
        /// <param name="torque">Movement tenacity.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?MoveTorque@@YAHEJ@Z",
            CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool MoveTorque(byte axis, int torque);

        /// <summary>
        /// Moves the robot without care for path
        /// </summary>
        /// <remarks>
        /// If <paramref name="vectorNameB"/> and <paramref name="pointNumberB"/> are set to null and 0 respectively, 
        /// the robot only moves to the first position.
        /// </remarks>
        /// <param name="vectorName">First vector name.</param>
        /// <param name="pointNumber">First vector point number.</param>
        /// <param name="vectorNameB">Second vector name.</param>
        /// <param name="pointNumberB">Second vector point number.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?MoveJoint@@YAHPADF0F@Z",
            CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool MoveJoint(string vectorName, short pointNumber,
            string vectorNameB, short pointNumberB);
       
        /// <summary>
        /// Moves the robot in a linear path
        /// </summary>
        /// <remarks>
        /// If <paramref name="vectorNameB"/> and <paramref name="pointNumberB"/> are set to null and 0 respectively, 
        /// the robot only moves to the first position.
        /// </remarks>
        /// <param name="vectorName">First vector name.</param>
        /// <param name="pointNumber">First vector point number.</param>
        /// <param name="vectorNameB">Second vector name.</param>
        /// <param name="pointNumberB">Second vector point number.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?MoveLinear@@YAHPADF0F@Z",
            CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool MoveLinear(string vectorName, short pointNumber,
            string vectorNameB, short pointNumberB);

        /// <summary>
        /// Moves the robot in a circular motion
        /// </summary>
        /// <remarks>
        /// If <paramref name="vectorNameB"/> and <paramref name="pointNumberB"/> are set to null and 0 respectively, 
        /// the robot only moves to the first position.
        /// </remarks>
        /// <param name="vectorNameA">First vector name.</param>
        /// <param name="pointNumberA">First vector point number.</param>
        /// <param name="targetPointNumber">Target point number.</param>
        /// <param name="vectorNameB">Second vector name.</param>
        /// <param name="pointNumberB">Second vector point number.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?MoveCircularVect@@YAHPADFF0F@Z",
            CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool MoveCircularVect(string vectorNameA, short pointNumberA,
            short targetPointNumber, string vectorNameB, short pointNumberB);

        /// <summary>
        /// Completely opens the gripper.
        /// </summary>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?OpenGripper@@YAHXZ",
            CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool OpenGripper();

        /// <summary>
        /// Completely closes the gripper.
        /// </summary>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?CloseGripper@@YAHXZ",
            CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool CloseGripper();

        /// <summary>
        /// Stops robot movement.
        /// </summary>
        /// <param name="axis">Movement axis.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?Stop@@YAHE@Z",
            CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool Stop(byte axis);

        /// <summary>
        /// Sets the default movement velocity.
        /// </summary>
        /// <param name="axis">Movement axis.</param>
        /// <param name="percent">Velocity in percent.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?Velocity@@YAHEF@Z",
            CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool Velocity(byte axis, short percent);

        /// <summary>
        /// Gets the width between the grippers fingers.
        /// </summary>
        /// <param name="percent">Width in percent.</param>
        /// <param name="metricValue">Width in milimeters.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?GetJaw@@YAHPAF0@Z",
            CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool GetJaw(out short percent, out short metricValue);

        /// <summary>
        /// Turns control on or off for a specific axis.
        /// </summary>
        /// <remarks>
        /// Control must be turned on, to use allmost all movement functions properly functions properly.
        /// MoveTorque is the exception.
        /// </remarks>
        /// <param name="axis">Movement axis.</param>
        /// <param name="isOn">Toggles control on/off.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?Control@@YAHEH@Z",
            CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool Control(byte axis, [MarshalAs(UnmanagedType.Bool)] bool isOn);

        /// <summary>
        /// Watch control status on the robot.
        /// </summary>
        /// <param name="watchControl">Callback used to watch the control changes.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?WatchControl@@YAHP6AXPAX@Z@Z",
            CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool WatchControl(WatchControlCallback watchControl);

        /// <summary>
        /// Stops watch control status on the robot.
        /// </summary>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?CloseWatchControl@@YAHXZ",
            CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool CloseWatchControl();

        /// <summary>
        /// Watch the homing process.
        /// </summary>
        /// <remarks>
        /// The callback functions parameters tells the status of the homing process.
        /// <para />
        /// The values are: 
        ///     0xff:  Homing started 
        ///     1 - 8: Axis 1 - 8 is being homed 
        ///     0x40:  Homing ended 
        /// <para />
        /// These values does not indicate succes or failure.
        /// </remarks>
        /// <param name="homingNotifier">Callback for when the homing status changes.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?WatchHoming@@YAHP6AXPAX@Z@Z",
            CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool WatchHoming(HomingNotifierCallback homingNotifier);

        /// <summary>
        /// Homes the robot.
        /// </summary>
        /// <remarks>
        /// The callback functions parameters tells the status of the homing process.
        /// <para />
        /// The values are: 
        ///     0xff:  Homing started 
        ///     1 - 8: Axis 1 - 8 is being homed 
        ///     0x40:  Homing ended 
        /// <para />
        /// These values does not indicate succes or failure.
        /// </remarks>
        /// <param name="axis">Movement axis.</param>
        /// <param name="homingNotifier">Callback for when the homing have completed.</param>
        /// <returns>Returns true if the homing process was a succes, false otherwise.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?Home@@YAHEP6AXPAX@Z@Z",
            CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool Home(byte axis, HomingNotifierCallback homingNotifier);

        /// <summary>
        /// Sets the home position to the current position.
        /// </summary>
        /// <remarks>
        /// Calling this function does NOT force the robot homed status, it only saves the position in a base vector.
        /// </remarks>
        /// <param name="axis">Movement axis.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?SetHome@@YAHE@Z",
            CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool SetHome(byte axis);

        /// <summary>
        /// Watch the values for each joint on the robot.
        /// </summary>
        /// <remarks>
        /// The interval between each callback is defined in USBC.ini in miliseconds.
        /// </remarks>
        /// <param name="watchJoint">Callback used to watch the joint changes.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?WatchJoint@@YAHP6AXPAX@Z@Z",
            CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool WatchJoint(WatchJointCallback watchJoint);

        /// <summary>
        /// Stops watch the joints status on the robot.
        /// </summary>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?CloseWatchJoint@@YAHXZ",
            CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool CloseWatchJoint();

        #endregion

        #region Positioning

        /// <summary>
        /// Loads points into the robots memory from a file.
        /// </summary>
        /// <param name="filename">The file to open.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?AddPoints@@YAHPAD@Z",
            CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool LoadPointsFromFile(string filename);

        /// <summary>
        /// Defines a vector in the robots memory.
        /// </summary>
        /// <param name="axis">Movement axis.</param>
        /// <param name="vectorName">Vector name.</param>
        /// <param name="dimension">Vector dimension.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?DefineVector@@YAHEPADF@Z",
            CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool DefineVector(byte axis, string vectorName, short dimension);

        /// <summary>
        /// Renames a vector in the robots memory.
        /// </summary>
        /// <param name="oldName">Old vector name.</param>
        /// <param name="newName">New vector name.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?RenameVector@@YAHPAD0@Z",
            CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool RenameVector(string oldName, string newName);

        /// <summary>
        /// Deletes a vector in the robots memory.
        /// </summary>
        /// <remarks>
        /// If <paramref name="pointNumber"/> is set to -1 then all of the vectors are deleted.
        /// </remarks>
        /// <param name="vectorName">Vector name.</param>
        /// <param name="pointNumber">Vector point number.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?DeletePoint@@YAHPADF@Z",
            CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool DeletePoint(string vectorName, short pointNumber);

        /// <summary>
        /// Saves a point in memory defined by the robots current position.
        /// </summary>
        /// <param name="vectorName">Vector name.</param>
        /// <param name="pointNumber">Vector point number.</param>
        /// <param name="pointType">Vector point type.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?Here@@YAHPADFJ@Z",
            CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool Here(string vectorName, short pointNumber, int pointType);

        /// <summary>
        /// Teaches a robot the location of a named vector.
        /// </summary>
        /// <param name="vectorName">Vector name.</param>
        /// <param name="pointNumber">Vector point number.</param>
        /// <param name="coordinates">Coordinates array.</param>
        /// <param name="dimension">Length of the coordinates array.</param>
        /// <param name="pointType">Vector point type.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?Teach@@YAHPADFPAJFJ@Z",
            CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool Teach(string vectorName, short pointNumber,
            int[] coordinates, short dimension, int pointType);

        /// <summary>
        /// SetJoints
        /// </summary>
        /// <param name="vectorName">Vector name.</param>
        /// <param name="pointNumber">Vector point number.</param>
        /// <param name="coordinates">Coordinates array.</param>
        /// <param name="dimension">Length of the coordinates array.</param>
        /// <param name="pointType">Vector point type.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?SetJoints@@YAHPADFPAJFJ@Z",
            CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool SetJoints(string vectorName, short pointNumber,
            int[] coordinates, short dimension, int pointType);

        /// <summary>
        /// Gets the point information for a given vector and point-number.
        /// </summary>
        /// <param name="vectorName">Vector name.</param>
        /// <param name="pointNumber">Vector point number.</param>
        /// <param name="encData">Axis rotations.</param>
        /// <param name="xyzData">XYZ coordinates.</param>
        /// <param name="pointType">Vector point type.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?GetPointInfo@@YAHPADFPAY07J11PAJ@Z",
            CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool GetPointInfo(string vectorName, short pointNumber,
            [MarshalAs(UnmanagedType.LPArray, SizeConst = USBC.TotalAxes)][Out] int[] encData,
            [MarshalAs(UnmanagedType.LPArray, SizeConst = USBC.TotalAxes)][Out] int[] xyzData,
            int pointType);

        /// <summary>
        /// Gets the current position of the robot.
        /// </summary>
        /// <param name="enc">Axis rotations.</param>
        /// <param name="joint">Bone joints.</param>
        /// <param name="xyz">XYZ coordinates.</param>
        /// <returns><c>true</c> if the method has been succesfully executed; otherwise, <c>false</c>.</returns>
        [DllImport(NativeMethods.DllName, EntryPoint = "?GetCurrentPosition@@YAHPAY07J00@Z",
            CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool GetCurrentPosition(
            [MarshalAs(UnmanagedType.LPArray, SizeConst = USBC.TotalAxes)][Out] int[] enc,
            [MarshalAs(UnmanagedType.LPArray, SizeConst = USBC.TotalAxes)][Out] int[] joint,
            [MarshalAs(UnmanagedType.LPArray, SizeConst = USBC.TotalAxes)][Out] int[] xyz);

        #endregion
    }
}
